package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"time"
)

// 对消息头进行解包
func UnPack(headBuf []byte) (msgLength uint32, msgId uint32, err error) {
	databuf := bytes.NewReader(headBuf)
	if err := binary.Read(databuf, binary.LittleEndian, &msgLength); err != nil {
		fmt.Println("client error unpack msg head: ", err)
		return 0, 0, err
	}

	if err := binary.Read(databuf, binary.LittleEndian, &msgId); err != nil {
		fmt.Println("client error unpack msg head: ", err)
		return 0, 0, err
	}

	return msgLength, msgId, nil
}

// 对消息进行打包
func Pack(msgId uint32, msgData []byte) ([]byte, error) {
	databuf := bytes.NewBuffer([]byte{})

	if err := binary.Write(databuf, binary.LittleEndian, int32(len(msgData))); err != nil {
		fmt.Println("cilent error when pack msgLength: ", err)
		return nil, err
	}

	if err := binary.Write(databuf, binary.LittleEndian, msgId); err != nil {
		fmt.Println("cilent error when pack msgId: ", err)
		return nil, err
	}

	if err := binary.Write(databuf, binary.LittleEndian, msgData); err != nil {
		fmt.Println("cilent error when pack msgData: ", err)
		return nil, err
	}

	return databuf.Bytes(), nil
}

func main() {
	fmt.Println("Client Start!")
	time.Sleep(1 * time.Second)

	conn, err := net.Dial("tcp", "127.0.0.1:8999")
	if err != nil {
		fmt.Println("Connnect to Server ERROR ", err)
		return
	}

	for {
		// 写消息到服务端

		// 先将消息进行打包
		msgBinary, err := Pack(2, []byte("Hello Zinx"))
		if err != nil {
			fmt.Println("pack msg error: ", err)
			break
		}

		// 再将消息写入流中
		if _, err := conn.Write(msgBinary); err != nil {
			fmt.Println("send msg error: ", err)
			break
		}

		// 先读取8位的消息头
		headBuf := make([]byte, 8)
		if _, err := io.ReadFull(conn, headBuf); err != nil {
			fmt.Println("error when read head from server: ", err)
			break
		}

		// 对消息头进行处理，读取msgId与消息长度
		msgLength, msgId, err := UnPack(headBuf)
		if err != nil {
			fmt.Println("unpack msg error: ", err)
			break
		}

		// 从服务端读取消息头
		bodyBuf := make([]byte, msgLength)
		if _, err := io.ReadFull(conn, bodyBuf); err != nil {
			fmt.Println("read msg body error: ", err)
			break
		}

		fmt.Printf("Read from Server, msgId: %d, msgData: %s \n", msgId, string(bodyBuf))
		time.Sleep(1 * time.Second)
	}

}
